/*
 * Copyright 2016-2019 yoara
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package yhao.infra.feature.payment.core.alipaynew;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import yhao.infra.feature.payment.core.alipaynew.model.pay.AliPayCallBackResult;
import yhao.infra.feature.payment.core.alipaynew.model.pay.AliPayModel;
import yhao.infra.feature.payment.core.alipaynew.model.refund.AliRefundModel;
import yhao.infra.feature.payment.core.alipaynew.model.refund.AliRefundQueryModel;
import yhao.infra.feature.payment.core.alipaynew.config.AliPayConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * ali支付核心处理类
 *
 * @author yoara
 */
public class AliPayService {
    private Logger logger = LoggerFactory.getLogger("paymentLogger");
    private AlipayClient alipayClient;
    private AliPayConfig alipayConfig;

    public AliPayService(AliPayConfig config) {
        this.alipayConfig = config;
        this.alipayClient = new DefaultAlipayClient(config.getAliPay_gateWay(),
                config.getApp_id(), config.getApp_private_key(), "json",
                config.getCharset(), config.getAli_public_key(), config.getSign_type());
    }

    public AliPayConfig pickConfig(){
        return alipayConfig;
    }

    private static final String SUCCESS_CODE = "10000";

    /**
     * 退款查询接口 如果该接口返回了查询数据，则代表退款成功，如果没有查询到则代表未退款成功
     */
    public String aliPayRefundQuery(AliRefundQueryModel model) throws Exception {
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        request.setBizContent(JSONObject.toJSONString(model));
        AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
        if (SUCCESS_CODE.equals(response.getCode())) {
            return response.getRefundAmount();
        } else {
            return null;
        }
    }

    /**
     * 退款接口
     *
     * @return 该笔交易已退款的总金额(double)
     */
    public String aliPayRefund(AliRefundModel model) throws Exception {
        AlipayTradeRefundModel refundModel = new AlipayTradeRefundModel();
        refundModel.setOutTradeNo(model.getOut_trade_no());
        refundModel.setTradeNo(model.getTrade_no());
        refundModel.setRefundAmount(model.getRefund_amount());
        refundModel.setRefundReason(StringUtils.isEmpty(model.getReason())?"退款":model.getReason());
        refundModel.setOutRequestNo(model.getOut_request_no());
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();//创建API对应的request类
        request.setBizModel(refundModel);//设置业务参数
        AlipayTradeRefundResponse response = alipayClient.execute(request);//通过alipayClient调用API，获得对应的response类
        if (SUCCESS_CODE.equals(response.getCode())) {
            return response.getRefundFee();
        } else {
            return null;
        }
    }


    /**
     * 阿里交易查询
     *
     * @param orderNo
     * @return
     */
    public AlipayTradeQueryResponse aliPayTradeQuery(String orderNo) throws Exception {
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();//创建API对应的request类
        JSONObject json = new JSONObject();
        json.put("out_trade_no", orderNo);
        request.setBizContent(json.toJSONString());//设置业务参数
        AlipayTradeQueryResponse response = alipayClient.execute(request);//通过alipayClient调用API，获得对应的response类
        //return SUCCESS_CODE.equals(response.getCode()) && "TRADE_SUCCESS".equals(response.getTradeStatus());
        return response;
    }


    public boolean isRefundCallBack(HttpServletRequest request) {
        return StringUtils.isNotBlank(request.getParameter("refund_fee"));
    }

    public AliPayCallBackResult payCallBackCheck(HttpServletRequest request) {
        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        logger.info("支付宝回调返回---->" + JSONObject.toJSONString(params));
        //切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        AliPayCallBackResult result = new AliPayCallBackResult();
        boolean flag;
        try {
            flag = AlipaySignature.rsaCheckV1(params,
                    alipayConfig.getAli_public_key(), alipayConfig.getCharset(), alipayConfig.getSign_type());
        } catch (AlipayApiException e) {
            logger.error("alipay支付回调验签出错!", e);
            result.setCheckPass(false);
            return result;
        }
        if (!flag) {
            return result;
        }
        result.setCheckPass(flag);
        result.setOrderId(request.getParameter("out_trade_no"));
        result.setPayTradeNo(request.getParameter("trade_no"));
        result.setApp_id(request.getParameter("app_id"));
        result.setAmount(new Double(request.getParameter("total_amount")));
        result.setSeller_id(request.getParameter("seller_id"));
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            result.setNotifyTime(dateFormat.parse(request.getParameter("notify_time")));
        } catch (ParseException e) {
            result.setNotifyTime(new Date());
        }
        if ("TRADE_SUCCESS".equals(request.getParameter("trade_status")) || "TRADE_FINISHED".equals(request.getParameter("trade_status"))) {
            result.setPaySuccess(true);
        } else {
            result.setPaySuccess(false);
        }
        return result;
    }

    /**
     * 生成App支付订单
     */
    public String generateAppOrderStr(AliPayModel payObject) {
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        request.setBizContent(JSONObject.toJSONString(payObject));
        request.setNotifyUrl(alipayConfig.getNotify_url_pre()+payObject.getNotifyUrl());
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            return response.getBody();
            //System.out.println(response.getBody());//就是orderString 可以直接给客户端请求，无需再做处理。
        } catch (AlipayApiException e) {
            logger.error("生成支付宝OrderStr出错", e.getMessage());
        }
        return null;
    }

    /**
     * 阿里Wap支付
     */
    public void generateWapPayHtml(AliPayModel payObject, HttpServletResponse httpResponse, String returnInfo) throws Exception {
        AlipayTradeWapPayRequest aliPayRequest = new AlipayTradeWapPayRequest();//创建API对应的request
        //"?orderNo=" + payObject.getOut_trade_no() + "&reqSource=" + PaySourceEnums.ALIPAY.name());
        aliPayRequest.setReturnUrl(alipayConfig.getReturn_url() + "?" + returnInfo);
        aliPayRequest.setNotifyUrl(alipayConfig.getNotify_url_pre()+payObject.getNotifyUrl());//在公共参数中设置回跳和通知地址
        aliPayRequest.setBizContent(JSONObject.toJSONString(payObject));//填充业务参数
        String form = alipayClient.pageExecute(aliPayRequest).getBody(); //调用SDK生成表单
        //logger.info("支付宝返回---->" + form);
        // return form;
        httpResponse.setContentType("text/html;charset=" + alipayConfig.getCharset());
        httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }

    /**
     * 阿里预创建（二维码）
     */
    public JSONObject generatePrecreate(AliPayModel payObject) throws Exception {
        AlipayTradePrecreateRequest aliPayRequest = new AlipayTradePrecreateRequest();//创建API对应的request
        aliPayRequest.setNotifyUrl(alipayConfig.getNotify_url_pre()+payObject.getNotifyUrl());//在公共参数中设置回跳和通知地址
        aliPayRequest.setBizContent(JSONObject.toJSONString(payObject));//填充业务参数
        return JSONObject.parseObject(
                alipayClient.execute(aliPayRequest).getBody()); //调用SDK生成表单
    }
}
